﻿using System;
using System.Collections.Generic;

namespace PlottingBasics.LINQHelpers
{
    public static class Integral
    {
        /// <summary>
        /// Returns an iterator class that sums the source.
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IEnumerable<Pair<TSource, TResult>> RunningSum<TSource, TResult>(this IEnumerable<TSource> source,
            Func<TResult, TSource, TResult> agragator,
            TResult initialValue)
        {
            return new IntegralItr<TSource, TResult>(source, agragator, initialValue);
        }

        /// <summary>
        /// A class that does the actual iteration for us
        /// </summary>
        /// <typeparam name="T"></typeparam>
        class IntegralItr<TSource, TResult> : IEnumerable<Pair<TSource, TResult>>
        {
            private IEnumerable<TSource> _source;
            private Func<TResult, TSource, TResult> _agragator;
            private TResult _initialValue;

            public IntegralItr(IEnumerable<TSource> source, Func<TResult, TSource, TResult> agragator, TResult initalValue)
            {
                this._source = source;
                this._agragator = agragator;
                this._initialValue = initalValue;
            }

            /// <summary>
            /// Returns an iterator that will keep a running sum
            /// </summary>
            /// <returns></returns>
            public System.Collections.Generic.IEnumerator<Pair<TSource, TResult>> GetEnumerator()
            {
                TResult total = _initialValue;

                foreach (var p in _source)
                {
                    total = this._agragator(total, p);
                    yield return new Pair<TSource, TResult>(p, total);
                }
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                throw new NotImplementedException();
            }
        }
    }
}
